home *** CD-ROM | disk | FTP | other *** search
- unit MoreLists;
-
- interface
-
- uses
- Classes, SysUtils;
-
- type
-
- TListNotifyEvent = procedure(Sender: TObject; Ptr: Pointer;
- Action: TListNotification) of Object;
-
- TNotifyList = class(TList)
- private
- FOnChange: TListNotifyEvent;
- protected
- procedure Notify(Ptr: Pointer; Action: TListNotification); override;
- public
- property OnChange: TListNotifyEvent read FOnChange write FOnChange;
- end;
-
- EBigQueueException = class(Exception);
-
- TBigQueue = class
- private
- LL: TList;
- NextPopIndex: Integer;
- NextPushIndex: Integer;
- PopList: TList;
- PushList: TList;
- protected
- procedure CreateNewItemList;
- public
- constructor Create;
- destructor Destroy; override;
- function Count: Integer;
- function AtLeast(ACount: Integer): Boolean;
- function HasItems: Boolean;
- procedure Push(AItem: Pointer);
- function Pop: Pointer;
- function Peek: Pointer;
- end;
-
- implementation
-
- { TBigQueue }
-
- const
- QUEUE_LIST_CAPACITY = 1024;
-
- function TBigQueue.AtLeast(ACount: Integer): Boolean;
- begin
- Result := ACount >= Count;
- end;
-
- function TBigQueue.Count: Integer;
- begin
- if PopList = PushList then
- Result := NextPushIndex - NextPopIndex
- else
- Result := QUEUE_LIST_CAPACITY - NextPopIndex + NextPushIndex;
- if LL.Count > 2 then
- Inc(Result, ((LL.Count - 2) * QUEUE_LIST_CAPACITY));
- end;
-
- constructor TBigQueue.Create;
- begin
- inherited Create;
- LL := TList.Create;
- CreateNewItemList;
- PopList := PushList;
- NextPushIndex := 0;
- NextPopIndex := 0;
- end;
-
- procedure TBigQueue.CreateNewItemList;
- begin
- PushList := TList.Create;
- PushList.Count := QUEUE_LIST_CAPACITY;
- NextPushIndex := 0;
- LL.Add(PushList);
- end;
-
- destructor TBigQueue.Destroy;
- var
- I: Integer;
- begin
- for I := 0 to (LL.Count - 1) do
- TList(LL[I]).Free;
- inherited Destroy;
- end;
-
- function TBigQueue.HasItems: Boolean;
- begin
- Result := (PopList <> PushList) or
- ((NextPopIndex + 1) < NextPushIndex);
- end;
-
- function TBigQueue.Peek: Pointer;
- begin
- if (PopList <> PushList) or
- (NextPopIndex < NextPushIndex) then
- Result := PopList[NextPopIndex]
- else
- raise EBigQueueException.Create('Pop or Peek invoked ' +
- 'when no item available');
- end;
-
- function TBigQueue.Pop: Pointer;
- begin
- Result := Peek;
- Inc(NextPopIndex);
- if (PopList = PushList) then
- begin
- if (NextPopIndex = NextPushIndex) then
- begin
- NextPopIndex := 0;
- NextPushIndex := 0;
- end;
- end
- else
- begin
- if (NextPopIndex = QUEUE_LIST_CAPACITY) then
- begin
- LL.Delete(0);
- PopList := TList(LL[0]);
- NextPopIndex := 0;
- end;
- end;
- end;
-
- procedure TBigQueue.Push(AItem: Pointer);
- begin
- if NextPushIndex = QUEUE_LIST_CAPACITY then
- CreateNewItemList;
- PushList[NextPushIndex] := AItem;
- Inc(NextPushIndex);
- end;
-
- { TNotifyList }
-
- procedure TNotifyList.Notify(Ptr: Pointer; Action: TListNotification);
- begin
- inherited Notify(Ptr, Action);
- if Assigned(FOnChange) then
- FOnChange(Self, Ptr, Action);
- end;
-
- end.
-